﻿using System;
using System.Collections.Generic;
using System.Text;

namespace RaisingStudio.Data.Expressions
{
    /// <summary>
    /// expression
    /// </summary>
    [Serializable]
    public class BinaryExpression : OperationElement
    {
        private BinaryOperator binaryOperator;
        public BinaryOperator BinaryOperator
        {
            get
            {
                return this.binaryOperator;
            }
            set
            {
                this.binaryOperator = value;
            }
        }

        private OperationElement operationElement;
        public OperationElement OperationElement
        {
            get
            {
                return this.operationElement;
            }
            set
            {
                this.operationElement = value;
            }
        }

        private List<BinaryExpression> children;
        public List<BinaryExpression> Children
        {
            get
            {
                if (this.children == null)
                {
                    this.children = new List<BinaryExpression>();
                }
                return this.children;
            }
        }

        public bool HasChildren
        {
            get
            {
                return ((this.children != null) && (this.children.Count > 0));
            }
        }
       
        #region Constructor
        public BinaryExpression()
        {
            this.children = new List<BinaryExpression>();
        }

        public BinaryExpression(OperationElement operationElement) : this()
        {
            this.operationElement = operationElement;
        }

        public BinaryExpression(OperationElement operationElement1, BinaryOperator binaryOperator, OperationElement operationElement2) : this()
        {
            BinaryExpression binaryExpression1 = new BinaryExpression(operationElement1);
            BinaryExpression binaryExpression2 = new BinaryExpression(operationElement2);
         
            this.Children.Add(binaryExpression1);
            binaryExpression2.BinaryOperator = binaryOperator;
            this.Children.Add(binaryExpression2);
        }

        public BinaryExpression(BinaryExpression binaryExpression1, BinaryOperator binaryOperator, BinaryExpression binaryExpression2) : this()
        {
            this.Children.Add(binaryExpression1);
            binaryExpression2.BinaryOperator = binaryOperator;
            this.Children.Add(binaryExpression2);
        }
        #endregion

        public void AddExpression(BinaryExpression binaryExpression)
        {
            this.Children.Add(binaryExpression);
        }

        public void AddExpression(OperationElement operationElement)
        {
            BinaryExpression binaryExpression = new BinaryExpression(operationElement);
            AddExpression(binaryExpression);
        }

        public void AddExpression(BinaryOperator binaryOperator, OperationElement operationElement)
        {
            BinaryExpression binaryExpression = new BinaryExpression(operationElement);
            binaryExpression.BinaryOperator = binaryOperator;
            AddExpression(binaryExpression);
        }

        #region 加
        public void Plus(BinaryExpression binaryExpression)
        {
            binaryExpression.BinaryOperator = BinaryOperator.Plus;
            this.Children.Add(binaryExpression);
        }

        public void Plus(OperationElement operationElement)
        {
            BinaryExpression binaryExpression = new BinaryExpression(operationElement);
            Plus(binaryExpression);
        }
        #endregion
        #region 减
        public void Minus(BinaryExpression binaryExpression)
        {
            binaryExpression.BinaryOperator = BinaryOperator.Minus;
            this.Children.Add(binaryExpression);
        }

        public void Minus(OperationElement operationElement)
        {
            BinaryExpression binaryExpression = new BinaryExpression(operationElement);
            Minus(binaryExpression);
        }
        #endregion
        #region 乘
        public void Multiply(BinaryExpression binaryExpression)
        {
            binaryExpression.BinaryOperator = BinaryOperator.Multiply;
            this.Children.Add(binaryExpression);
        }

        public void Multiply(OperationElement operationElement)
        {
            BinaryExpression binaryExpression = new BinaryExpression(operationElement);
            Multiply(binaryExpression);
        }
        #endregion
        #region 除
        public void Divide(BinaryExpression binaryExpression)
        {
            binaryExpression.BinaryOperator = BinaryOperator.Divide;
            this.Children.Add(binaryExpression);
        }

        public void Divide(OperationElement operationElement)
        {
            BinaryExpression binaryExpression = new BinaryExpression(operationElement);
            Divide(binaryExpression);
        }
        #endregion
        #region 求模
        public void Modulo(BinaryExpression binaryExpression)
        {
            binaryExpression.BinaryOperator = BinaryOperator.Modulo;
            this.Children.Add(binaryExpression);
        }

        public void Modulo(OperationElement operationElement)
        {
            BinaryExpression binaryExpression = new BinaryExpression(operationElement);
            Modulo(binaryExpression);
        }
        #endregion

        public void AddPlusExpression(params BinaryExpression[] binaryExpressions)
        {
            foreach (BinaryExpression binaryExpression in binaryExpressions)
            {
                binaryExpression.BinaryOperator = BinaryOperator.Plus;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddPlusExpression(params OperationElement[] operationElements)
        {
            foreach (OperationElement operationElement in operationElements)
            {
                BinaryExpression binaryExpression = new BinaryExpression(operationElement);
                binaryExpression.BinaryOperator = BinaryOperator.Plus;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddMinusExpression(params BinaryExpression[] binaryExpressions)
        {
            foreach (BinaryExpression binaryExpression in binaryExpressions)
            {
                binaryExpression.BinaryOperator = BinaryOperator.Minus;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddMinusExpression(params OperationElement[] operationElements)
        {
            foreach (OperationElement operationElement in operationElements)
            {
                BinaryExpression binaryExpression = new BinaryExpression(operationElement);
                binaryExpression.BinaryOperator = BinaryOperator.Minus;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddMultiplyExpression(params BinaryExpression[] binaryExpressions)
        {
            foreach (BinaryExpression binaryExpression in binaryExpressions)
            {
                binaryExpression.BinaryOperator = BinaryOperator.Multiply;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddMultiplyExpression(params OperationElement[] operationElements)
        {
            foreach (OperationElement operationElement in operationElements)
            {
                BinaryExpression binaryExpression = new BinaryExpression(operationElement);
                binaryExpression.BinaryOperator = BinaryOperator.Multiply;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddDivideExpression(params BinaryExpression[] binaryExpressions)
        {
            foreach (BinaryExpression binaryExpression in binaryExpressions)
            {
                binaryExpression.BinaryOperator = BinaryOperator.Divide;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddDivideExpression(params OperationElement[] operationElements)
        {
            foreach (OperationElement operationElement in operationElements)
            {
                BinaryExpression binaryExpression = new BinaryExpression(operationElement);
                binaryExpression.BinaryOperator = BinaryOperator.Divide;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddModuloExpression(params BinaryExpression[] binaryExpressions)
        {
            foreach (BinaryExpression binaryExpression in binaryExpressions)
            {
                binaryExpression.BinaryOperator = BinaryOperator.Modulo;
                this.Children.Add(binaryExpression);
            }
        }

        public void AddModuloExpression(params OperationElement[] operationElements)
        {
            foreach (OperationElement operationElement in operationElements)
            {
                BinaryExpression binaryExpression = new BinaryExpression(operationElement);
                binaryExpression.BinaryOperator = BinaryOperator.Modulo;
                this.Children.Add(binaryExpression);
            }
        }

        #region type 转换
        public static implicit operator BinaryExpression(ColumnExpression value)
        {
            return new BinaryExpression(value);
        }

        public static implicit operator BinaryExpression(FunctionExpression value)
        {
            return new BinaryExpression(value);
        }
        #endregion

        #region 符重载
        public static BinaryExpression operator +(BinaryExpression binaryExpression1, BinaryExpression binaryExpression2)
        {
            return new BinaryExpression(binaryExpression1, BinaryOperator.Plus, binaryExpression2);
        }

        public static BinaryExpression operator -(BinaryExpression binaryExpression1, BinaryExpression binaryExpression2)
        {
            return new BinaryExpression(binaryExpression1, BinaryOperator.Minus, binaryExpression2);
        }

        public static BinaryExpression operator *(BinaryExpression binaryExpression1, BinaryExpression binaryExpression2)
        {
            return new BinaryExpression(binaryExpression1, BinaryOperator.Multiply, binaryExpression2);
        }

        public static BinaryExpression operator /(BinaryExpression binaryExpression1, BinaryExpression binaryExpression2)
        {
            return new BinaryExpression(binaryExpression1, BinaryOperator.Divide, binaryExpression2);
        }

        public static BinaryExpression operator %(BinaryExpression binaryExpression1, BinaryExpression binaryExpression2)
        {
            return new BinaryExpression(binaryExpression1, BinaryOperator.Modulo, binaryExpression2);
        }
        #endregion
    }
}
